﻿#region Copyright
// Copyright (c) 2011-2012 RaisingForce Team (Alikin Sergey)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion

using RaisingForce.Raise.Measures;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using System.Globalization;

namespace RaisingForce.Raise.Tests
{


    /// <summary>
    ///Это класс теста для AngleTest, в котором должны
    ///находиться все модульные тесты AngleTest
    ///</summary>
    [TestClass()]
    public class AngleTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Получает или устанавливает контекст теста, в котором предоставляются
        ///сведения о текущем тестовом запуске и обеспечивается его функциональность.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Дополнительные атрибуты теста
        // 
        //При написании тестов можно использовать следующие дополнительные атрибуты:
        //
        //ClassInitialize используется для выполнения кода до запуска первого теста в классе
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //ClassCleanup используется для выполнения кода после завершения работы всех тестов в классе
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //TestInitialize используется для выполнения кода перед запуском каждого теста
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //TestCleanup используется для выполнения кода после завершения каждого теста
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///Тест для ToString
        ///</summary>
        [TestMethod()]
        public void ToStringTest()
        {
            // default -> UnknownString
            Angle target = new Angle();
            string format = null;
            IFormatProvider formatProvider = null;
            string expected = Angle.UnknownString;
            string actual;
            actual = target.ToString(format, formatProvider);
            Assert.AreEqual(expected, actual);
            // unknown -> UnknownString
            target = Angle.Unknown;
            expected = Angle.UnknownString;
            actual = target.ToString();
            Assert.AreEqual(expected, actual);
            // PI/4 -> 45 degree
            target = Angle.DefineInRadian(Math.PI / 4);
            expected = "45\u00B0";
            actual = target.ToString();
            Assert.AreEqual(expected, actual);
            // PI/4 -> 45.00 degree
            expected = "45.00\u00B0";
            actual = target.ToString("F2", CultureInfo.InvariantCulture);
            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void SerializationTest()
        {
            // default
            Angle actual = new Angle();
            Angle expected = Angle.Unknown;
            SerializationHelper.Test(ref actual);
            Assert.AreEqual(expected, actual);
            // unknown
            actual = Angle.Unknown;
            expected = Angle.Unknown;
            SerializationHelper.Test(ref actual);
            Assert.AreEqual(expected, actual);
            // 90 degree
            actual = Angle.DefineInDegree(90);
            expected = Angle.DefineInDegree(90);
            SerializationHelper.Test(ref actual);
            Assert.AreEqual(expected, actual);
            // PI/4 radian
            actual = Angle.DefineInRadian(Math.PI / 4);
            expected = Angle.DefineInRadian(Math.PI / 4);
            SerializationHelper.Test(ref actual);
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///Тест для op_Addition
        ///</summary>
        [TestMethod()]
        public void op_AdditionTest()
        {
            // default + default = unknown
            Angle first = new Angle();
            Angle second = new Angle();
            Angle expected = Angle.Unknown;
            Angle actual;
            actual = (first + second);
            Assert.AreEqual(expected, actual);
            // default + unknown = unknown + default = unknown
            first = new Angle();
            second = Angle.Unknown;
            expected = Angle.Unknown;
            actual = (first + second);
            Assert.AreEqual(expected, actual);
            actual = (second + first);
            Assert.AreEqual(expected, actual);
            // unknown + unknown = unknown
            first = Angle.Unknown;
            second = Angle.Unknown;
            expected = Angle.Unknown;
            actual = (first + second);
            Assert.AreEqual(expected, actual);
            // PI + unknown = unknown + PI = unknown
            first = Angle.DefineInRadian(Math.PI);
            second = Angle.Unknown;
            expected = Angle.Unknown;
            actual = (first + second);
            Assert.AreEqual(expected, actual);
            actual = (second + first);
            Assert.AreEqual(expected, actual);
            // PI + 90 = 90 + PI = 270
            first = Angle.DefineInRadian(Math.PI);
            second = Angle.DefineInDegree(90);
            expected = Angle.DefineInDegree(270);
            actual = (first + second);
            Assert.AreEqual(expected, actual);
            actual = (second + first);
            Assert.AreEqual(expected, actual);
            // 45 + PI/2 = PI/2 + 45 = 3 * PI/4
            first = Angle.DefineInDegree(45);
            second = Angle.DefineInRadian(Math.PI / 2);
            expected = Angle.DefineInRadian(3 * Math.PI / 4);
            actual = (first + second);
            Assert.AreEqual(expected, actual);
            actual = (second + first);
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///Тест для Get
        ///</summary>
        [TestMethod()]
        public void GetTest()
        {
            // default angle
            Angle target = new Angle();
            IAngleMeasure measure = AngleMeasures.Degree;
            double expected = Angle.UnknownValue;
            double actual;
            actual = target.Get(measure);
            Assert.AreEqual(expected, actual);
            measure = AngleMeasures.Radian;
            actual = target.Get(measure);
            Assert.AreEqual(expected, actual);
            // unknown angle
            target = Angle.Unknown;
            measure = AngleMeasures.Degree;
            expected = Angle.UnknownValue;
            actual = target.Get(measure);
            Assert.AreEqual(expected, actual);
            measure = AngleMeasures.Radian;
            actual = target.Get(measure);
            Assert.AreEqual(expected, actual);
            // 90 degree
            target = Angle.DefineInDegree(90);
            measure = AngleMeasures.Degree;
            expected = 90;
            actual = target.Get(measure);
            Assert.AreEqual(expected, actual);
            measure = AngleMeasures.Radian;
            expected = Math.PI / 2;
            actual = target.Get(measure);
            Assert.AreEqual(expected, actual);
            // PI radian
            target = Angle.DefineInRadian(Math.PI);
            measure = AngleMeasures.Radian;
            expected = Math.PI;
            actual = target.Get(measure);
            Assert.AreEqual(expected, actual);
            measure = AngleMeasures.Degree;
            expected = 180;
            actual = target.Get(measure);
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///Тест для GetNormalized
        ///</summary>
        [TestMethod()]
        public void GetNormalizedTest()
        {
            // default angle
            Angle target = new Angle();
            Angle expected = Angle.Unknown;
            Angle actual;
            actual = target.GetNormalized();
            Assert.AreEqual(expected, actual);
            // unknown angle
            target = Angle.Unknown;
            expected = Angle.Unknown;
            actual = target.GetNormalized();
            Assert.AreEqual(expected, actual);
            // 270 degree
            target = Angle.DefineInDegree(270);
            expected = new Angle(270, AngleMeasures.Degree);
            actual = target.GetNormalized();
            Assert.AreEqual(expected, actual);
            //// -270 degree
            //target = Angle.DefineInDegree(-270);
            //expected = Angle.DefineInRadian(Math.PI / 2);
            //actual = target.GetNormalized();
            //Assert.AreEqual(expected, actual);
            // 5 * PI
            target = new Angle(5 * Math.PI, AngleMeasures.Radian);
            expected = Angle.DefineInDegree(180);
            actual = target.GetNormalized();
            Assert.AreEqual(expected, actual);
            //// -5 * PI/2
            //target = Angle.DefineInRadian(-5 * Math.PI / 2);
            //expected = Angle.DefineInRadian(3 * Math.PI / 2);
            //actual = target.GetNormalized();
            //Assert.AreEqual(expected, actual);
        }
    }
}
